//
//  CSNavigationService.swift
//  Cycling
//
//  Created by CSS on 4/3/23.
//

import UIKit

import MapboxCoreNavigation
import MapboxDirections
import Turf
import MapboxMaps
import MapboxNavigation
import YYKit

class CSNavigationService {
    
    lazy private var heardBeat: Heartbeat = {
        let heardBeat: Heartbeat = .sharedInstance
        
        heardBeat.listen(name: "MapNavigation", inteval: 1, times: 0) { [weak self]point in
            self?.sendHeardData()
        }
        
        return heardBeat
    }()
    
    private var cid: Int = 0
    
    public var navigationService: NavigationService!
    
    public var sourcePoints: [CLLocationCoordinate2D] = []
}

// MARK: 对外访问类
extension CSNavigationService {
    
    func beginService(onComplete complete: ((Bool) -> Void)?) {
        let points = navigationService.routeProgress.routeOptions.waypoints
        guard points.count > 1 else {
            complete?(false)
            return
        }
        let waypoints: [Waypoint] = Array(navigationService.route.legs.compactMap({ $0.destination }))
        
        var features = [Turf.Feature]()
        for (waypointIndex, waypoint) in waypoints.enumerated() {
            var feature = Feature(geometry: .point(Point(waypoint.coordinate)))
            feature.properties = [
                "waypointCompleted": .boolean(waypointIndex < 0),
                "name": .number(Double(waypointIndex + 1)),
            ]
            features.append(feature)
        }
        
        let shape = FeatureCollection(features: features)
        let jsonString: String
        if let jsonData = try? JSONEncoder().encode(shape) {
            jsonString = String(data: jsonData, encoding: .utf8) ?? ""
        } else {
            jsonString = ""
        }
        MapRequest.postStartNavigation(withParams: [
            "equipmentid" : "1", "user_post" : "经开广场", "user_lng" : points.first!.coordinate.latitude, "user_lat" : points.first!.coordinate.longitude, "end_post" : "二七纪念塔", "end_lng" : points.last!.coordinate.latitude, "end_lat" : points.last!.coordinate.longitude, "distance" : navigationService.route.distance / 1000, "estimatedDuration" : navigationService.route.expectedTravelTime, "json" : jsonString
        ]) {[weak self] in
            if !$0 {
                complete?(false)
                return
            }
            guard let self = self else {
                return
            }
            self.cid = $1
            complete?(true)
            self.heardBeat.run()
        }
    }
    
    func startService(onComplete complete:((Bool) -> Void)?) {
        if cid == 0 {
            complete?(false)
            return
        }
        MapRequest.postMapRequestAndRequestStatusFoAPI(Map_Riding_API_Suspendend, andParams: ["cid" : cid, "state" : 1]) { [weak self]success, reason in
            if(success) {
                self?.navigationService.start()
                self?.heardBeat.start()
            }
            complete?(success)
        }
    }
    
    func stopService(onComplete complete:((Bool) -> Void)?) {
        if cid == 0 {
            complete?(false)
            return
        }
        MapRequest.postMapRequestAndRequestStatusFoAPI(Map_Riding_API_Suspendend, andParams: ["cid" : cid, "state" : 2]) { [weak self]success, reason in
            if(success) {
                self?.navigationService.stop()
                self?.heardBeat.pause()
            }
            complete?(success)
        }
        
        print("\((sourcePoints.reduce([], { $0 + [["lat" : $1.latitude, "lon" : $1.longitude]] }) as NSArray).mj_JSONString() ?? "")")
    }
    
    func endNavigation() {
        if cid == 0 {
            return
        }
        MapRequest.postMapRequestAndRequestStatusFoAPI(Map_Riding_API_Suspendend, andParams: ["cid" : cid, "state" : 3]) { [weak self]success, reason in
            if(success) {
                self?.stopService(onComplete: nil)
                self?.navigationService.endNavigation(feedback: .none)
            }
        }
    }
    
    func autoEndNavigation() {
        print("\((sourcePoints as NSArray).mj_JSONString() ?? "")")
    }
    
    private func sendHeardData() {
        if cid == 0 {
            return
        }
        guard let currentLocal = navigationService.locationManager.location else {
            return
        }
        let jsonString = (["lat" : currentLocal.coordinate.latitude, "lng" : currentLocal.coordinate.longitude] as NSDictionary).mj_JSONString()
        MapRequest.postNavigatingData(withParams: ["cid" : cid, "heartbeat" : jsonString as Any]) { success, reason in
            
        }
        sourcePoints.append(currentLocal.coordinate)
    }
    
}

// MARK: 对外访问类(页面跳转)
extension CSNavigationService {
    
    class func showMapNavigation(withIndexRouteResponse indexRouteResponse: IndexedRouteResponse, presentingVC: UIViewController) -> CSNavigationService {
        
        let currentNavigationService: CSNavigationService = .init()
        
        let navigationService = MapboxNavigationService(indexedRouteResponse: indexRouteResponse, credentials: NavigationSettings.shared.directions.credentials, simulating: .always)
        
        let topBannerVC = CSNavigationTopBannerViewController()
        let bottomBannerView = CSNavigationBottomBannerViewController()
        
        topBannerVC.topActionBlock = { type in
            if type == 0 {
                currentNavigationService.endNavigation()
                presentingVC.presentedViewController?.dismiss(animated: true)
            }
        }
        
        bottomBannerView.bannerActionTypeBlock = { type in
            if type == 0 {
                presentingVC.presentedViewController?.dismiss(animated: true)
            }
        }
        bottomBannerView.navigationService = currentNavigationService
        currentNavigationService.navigationService = navigationService
        currentNavigationService.beginService { success in
//            if !success {
//                return
//            }
            let navigationOptions = NavigationOptions(navigationService: navigationService, voiceController: .init(navigationService: navigationService, speechSynthesizer: SystemSpeechSynthesizer()), topBanner: topBannerVC, bottomBanner: bottomBannerView)
            let navigationVC = NavigationViewController(for: indexRouteResponse, navigationOptions: navigationOptions)
            
            navigationVC.navigationMapView?.routeCasingColor = .color(withHexString: "#0FDAB2")
            navigationVC.navigationMapView?.trafficUnknownColor = .color(withHexString: "#0FDAB2")
            navigationVC.navigationMapView?.traversedRouteColor = .color(withHexString: "#808080")
            navigationVC.routeLineTracksTraversal = true
                    
            navigationVC.modalPresentationStyle = .fullScreen
            presentingVC.present(navigationVC, animated: true)
        }
        return currentNavigationService
    }
    
}
